package blue.datacenter2;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import blue.platform.ServerInterface;


public class DataCenter implements ServerInterface{
	/*Handler for deal with Subscriber message .Every subscriber corresponding
	 * to a thread.*/
	private ArrayList<MasterHandler> master_sub_list_;
	/*Publisher list.*/
	private ArrayList<ZmqPublisher>  master_pub_list_;
	/* Handler for deal with Machine message. Every machine connection
	 * corresponding to a thread.*/
	private ArrayList<MachineHandler> mach_list_;
	/* Machine connection list. */
	private ArrayList<SocketClient> mach_conn_list_;
	/* Publisher for logger. */
	private ZmqPublisher log_pub_;

	public DataCenter(ArrayList<String> mach_ip_list, ArrayList<String> mach_port_list
			, String master_sub_port, String master_pub_port, String log_port)
	{
		master_pub_list_ = new ArrayList<ZmqPublisher>();
		master_sub_list_ = new ArrayList<MasterHandler>();
		// Create logger publisher
		log_pub_ = new ZmqPublisher(log_port);
		// Create connection to Machine
		mach_conn_list_ = initMachineConn(mach_ip_list,mach_port_list);
		// Create master
		initMasterHandler(master_sub_port,master_pub_port,log_pub_);
		// Create machine
		initMachineHandler(log_pub_);
	}

	private void initMasterHandler(String sub_port
		, String pub_port, ZmqPublisher log_pub)
	{
		// Create publisher for master
		ZmqPublisher master_pub = new ZmqPublisher(pub_port);
		master_pub_list_.add(master_pub);
		// Create subscriber for master
		MasterHandler master_sub= new MasterHandler(sub_port,log_pub);
		master_sub_list_.add(master_sub);
		// Register machine connection
		for(Iterator<SocketClient> it=mach_conn_list_.iterator(); it.hasNext();){
			master_sub.addWriteConn(it.next());
		}
	}

	/* This will initialize all of Handler for Machine. */
	private void initMachineHandler(ZmqPublisher log_pub)
	{
		mach_list_= new ArrayList<MachineHandler>();
		
		/* Create Handler for every Machine-Connection. */
		for(Iterator<SocketClient> it_i = mach_conn_list_.iterator();it_i.hasNext();) {
			SocketClient machine_obj = it_i.next();
			MachineHandler conn = new MachineHandler(machine_obj,log_pub);
			mach_list_.add(conn);
			/* Register all of master_pulisher for Machine_Handler. Machine 
			 * Message will be publish to them.*/
			for(Iterator<ZmqPublisher> it_j = master_pub_list_.iterator();it_j.hasNext();){
				ZmqPublisher pub_obj = it_j.next();
				conn.addPubConn(pub_obj);
			}
		}
 	}

	public ArrayList<SocketClient> initMachineConn(ArrayList<String> ip_list
		,ArrayList<String> port_list)
	{
		ArrayList<SocketClient> mach_list = new ArrayList<SocketClient>();
		String ip = "";
		String port = "";
		try{
			for(Iterator<String> it_ip=ip_list.iterator();it_ip.hasNext();){
				ip = it_ip.next();
				for(Iterator<String> it_port=port_list.iterator();it_port.hasNext();){
					port = it_port.next();
					System.out.println("Connect to machine > "+ip+":"+port);
					SocketClient conn = new SocketClient(ip,Integer.parseInt(port));
					mach_list.add(conn);
				}
			}

		}catch(IOException e){
			e.printStackTrace();
			System.out.println("Connect failed to "+ip+":"+port);
			System.exit(-1);
		}

		return mach_list;
	}

	@Override
	public void start_server() {
		for(Iterator<MasterHandler> it=master_sub_list_.iterator();it.hasNext();) {
			it.next().start();
		}

		for(Iterator<MachineHandler> it=mach_list_.iterator(); it.hasNext();) {
			it.next().start();
		}
	}
};